      <h1 class="entry-title entry-title-single" itemprop="headline">ABAP 开发系列(05): ABAP 内表与内表结构</h1>

    <div class="entry-content entry-content-single entry-content-aside" itemprop="text">
      <h2>2.内表和<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/internal-table-structure" title="查看内表结构中的全部文章" target="_blank">内表结构</a></span></h2>
<p><b>2.1  结构体(<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/structure" title="查看Structure中的全部文章" target="_blank">Structure</a></span>)</b></p>
<p><b>2.1.1 结构体的定义</b></p>
<p><span class='wp_keywordlink'><a href="http://www.sapjx.com/tag/sap-abap" title="ABAP" target="_blank">ABAP</a></span> 中可以定义结构来包含多个基本类型，便于整理及操作；</p>
<p>结构体不属于数据字典对象（数据字典中可以定义结构体，但不能存储数据），在程序运行时会被作为临时对象存储在内存空间；</p>
<p>在创建内表时，可参考直接定义的结构体作为<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/internal-table-structure" title="查看内表结构中的全部文章" target="_blank">内表结构</a></span>。</p>
<p>结构体的定义，可以通过两种方式实现：</p>
<p>&nbsp;</p>
<p><span id="more-216"></span><br />
<b>1.第一种方式</b></p>
<p>语法：<br />
<span style="color: #ff0000; background-color: #fff000;"><strong><br />
DATA:  BEGIN OF &lt;name&gt;</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>          &lt;field1&gt; . . .</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>          &lt;field2&gt; . . .</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>          . . .</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>      END OF &lt;name&gt;.</strong></span></p>
<p>&nbsp;</p>
<p>如：</p>
<pre class="brush: abap;">

TABLES: TABNA.

DATA: BEGIN OF ADDRESS,
       FLAG   TYPE C,
       ID     LIKE TABNA-ID,
       NAME1  LIKE TABNA-NAME1,
       CITY   LIKE TABNA-CITY,
      END OF ADDRESS.

* 为结构体字段赋值
  MOVE 'X'            TO ADDRESS-FLAG.
  MOVE '0001'         TO ADDRESS-ID.
  MOVE 'Smith'        TO ADDRESS-NAME1.
  MOVE 'Philadelphia' TO ADDRESS-CITY.

  WRITE ADDRESS.

</pre>
<p>&nbsp;</p>
<p><b>2.第二种方式</b></p>
<p>语法：<br />
<span style="color: #ff0000; background-color: #fff000;"><strong><br />
TYPES: BEGIN OF &lt;name1&gt;,</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>        &lt;field1&gt; . . . ,</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>        &lt;field2&gt; . . . ,</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>        . . .  ,</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>       END OF &lt;name1&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>DATA:  &lt;name2&gt; TYPE  &lt;name1&gt;.</strong></span></p>
<p>如：</p>
<pre class="brush: abap;">

TYPES: BEGIN OF ADDR,
        FLAG,
        ID      LIKE EMPLOYEE-ID,
        NAME1   LIKE EMPLOYEE-NAME1,
        CITY    LIKE EMPLOYEE-CITY,
       END OF ADDR.

DATA: ADDRESS TYPE ADDR.

MOVE:  'X'            TO ADDRESS-FLAG,
       '00001'        TO ADDRESS-ID,
       'Smith'        TO ADDRESS-NAME1,
       'Philadelphia' TO ADDRESS-CITY.

WRITE ADDRESS.

</pre>
<p>&nbsp;<br />
&nbsp;</p>
<p><b>2.1.2  </b><b>结构体的赋值</b></p>
<p>相同结构体之间可以通过 <b style="color:red;">MOVE … TO …</b> 语句进行赋值；</p>
<p>如若存在类型差异的结构体，则可以通过 <b style="color:red;"> MOVE-CORRESSPONDING … TO … </b> 语句将两个结构体之间相同字段自动匹配赋值:</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_05_Structure_Set_Value.png" alt="abap_05_Structure_Set_Value" width="365" height="194" class="alignnone size-full wp-image-495" /></p>
<p>与基本变量定义类似，结构体的初始化操作也可以通过 <strong style="color:red;">CLEAR</strong> 语句实现。</p>
<p>如：</p>
<pre class="brush: abap;">

TABLES: employee.

DATA: BEGIN OF address,
        flag,
        id      LIKE employee-id,
        name    LIKE employee-name1,
        city    LIKE employee-city,
      END OF ADDRESS.

SELECT * FROM employee.

     MOVE-CORRESPONDING employee TO address.

     WRITE: / address-flag,  address-id,
            address-name, address-city.

     CLEAR address.
ENDSELECT.

</pre>
<p>&nbsp;<br />
&nbsp;</p>
<p><b>2.2  </b><b>内表(<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/internal-table" title="查看Internal Table中的全部文章" target="_blank">Internal Table</a></span>)</b></p>
<p>内表与结构体基本类似，同样在程序运行过程中存储在临时创建的内存空间，它是一个可以存储多条记录的数据表。</p>
<p>&nbsp;</p>
<p><b>2.2.1 </b><b>内表的定义</b></p>
<p>通过关键字DATA定义内表，可以直接参考结构体或者其他内表及透明表结构，也可以直接定义结构字段。</p>
<p>语法：</p>
<p>①.<span style="color: #ff0000; background-color: #fff000;"><strong>DATA &lt;NAME&gt; TYPE &lt;STRUCTURE&gt;        WITH [UNIQUE|NON-UNIQUE] [INITIAL SIZE n] [WITH HEADER LINE].</strong></span></p>
<p>②.<span style="color: #ff0000; background-color: #fff000;"><strong>DATA &lt;NAME&gt; LIKE TABLE OF &lt;TABLE&gt; WITH [UNIQUE|NON-UNIQUE] [INITIAL SIZE n] [WITH HEADER LINE].</strong></span></p>
<p>③.<span style="color: #ff0000; background-color: #fff000;"><strong>DATA: BEGIN OF itab OCCURS n,</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>&lt;field&gt;</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>&lt;field&gt;</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>END OF itab.</strong></span></p>
<p>&nbsp;</p>
<p>其中，关键字说明如下：</p>
<p><b>[UNIQUE|NON-UNIQUE]</b>： 指定关键字，只用于排序表，使用NON-UNIQUE关键字的话，排序表数据记录允许重复关键字字段；</p>
<p><b>[INITIAL SIZE n]</b>：指定初始化内表大小，比较少用，一般默认即可；</p>
<p><b>[WITH HEADER LINE]</b>： 定义内表是否带表头；</p>
<p>&nbsp;</p>
<pre class="brush: abap;">
*--------------------------------------------------------------------*
* 通过定义结构体并参考该结构定义内表
*--------------------------------------------------------------------*
TABLES: employee.                           "参考某一透明表，必须先引用定义

TYPES:  BEGIN OF emp,
         id          LIKE employee-id,
         name1       LIKE employee-name1,
         country     LIKE employee-country,
        END OF emp.

*--------------------------------------------------------------------*
* 参考EMP 结构定义一个初始化大小为10，并有HEADER LINE的内表
*--------------------------------------------------------------------*
DATA: emptab TYPE STANDARD TABLE OF emp INITIAL SIZE 10 WITH HEADER LINE.


*--------------------------------------------------------------------*
* 参考EMPTAB内表，重新定义没有HEADER LINE的内表
*--------------------------------------------------------------------*
DATA: emptab_n LIKE STANDARD TABLE OF emptab.


*--------------------------------------------------------------------*
* 定义一个允许重复KEY，并且没有HEADER LINE的排序表
*--------------------------------------------------------------------*
DATA: emptab_s TYPE SORT TABLE OF emp WITH NON-UNIQUE KEY id.


*--------------------------------------------------------------------*
* 通过第三种方式定义的内表，可指定具体字段，默认内表存在HEADER LINE
*--------------------------------------------------------------------*
TYPES:  BEGIN OF emp OCCURS 0,
          id         LIKE employee-id,
          name1      LIKE employee-name1,
          country    LIKE employee-country,
        END OF emp.

</pre>
<p>&nbsp;</p>
<p><b>2.2.2  </b><b>内表有无 HEADER LINE </b><b>的区别</b></p>
<p>对于有HEADER LINE的内表，可以通过填充HEADER LINE数据后或通过 <b>外部</b><b><span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/work-area" title="查看Work Area中的全部文章" target="_blank">Work Area</a></span></b> 向内表存储空间中追加数据。</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_05_Internal_Table_With_Header_Line.png" alt="abap_05_Internal_Table_With_Header_Line" width="520" height="331" class="alignnone size-full wp-image-494" /></p>
<p>&nbsp;</p>
<p>对于没有HEADER LINE的内表，只能通过 <b>外部</b><b><span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/work-area" title="查看Work Area中的全部文章" target="_blank">Work Area</a></span></b>来传递数据：</p>
<p><img src="http://www.sapjx.com/wp-content/uploads/2014/03/abap_05_Internal_Table_Without_Header_Line.png" alt="abap_05_Internal_Table_Without_Header_Line" width="514" height="341" class="alignnone size-full wp-image-493" /></p>
<p>语法：</p>
<p>①.<span style="color: #ff0000; background-color: #fff000;"><strong>APPEND [&lt;<span class='wp_keywordlink_affiliate'><a href="http://www.sapjx.com/tag/work-area" title="查看Work Area中的全部文章" target="_blank">Work Area</a></span>&gt; INTO] &lt;ITAB&gt;.</strong></span></p>
<p>如：</p>
<pre class="brush: abap;">
TABLES: employee.

TYPES: BEGIN OF emp,
	id	LIKE employee-id,
	name1	LIKE employee-name1,
	country	LIKE employee-country,
       END OF emp.

* 有 HEADER LINE 的内表
DATA: emptab  TYPE STANDARD TABLE OF emp INITIAL SIZE 10 WITH HEADER LINE.

* 没有 HEADER LINE 的内表
DATA: emptab2 TYPE STANDARD TABLE OF emp INITIAL SIZE 10,         

* Work Area
      emptab_wa TYPE emp.                                                                           

SELECT * FROM employee.

    MOVE-CORRESPONDING employee TO emptab.
    APPEND emptab.

    MOVE-CORRESPONDING employee TO emptab_wa.
    APPEND emptab_wa TO emptab2.

ENDSELECT.

</pre>
<p>&nbsp;</p>
<p>由于没有HEADER LINE的内表通过Work Area 传递数据在性能上会优于HEADER LINE直接填充HEADER LINE，</p>
<p>所以，一般基本都使用没有 HEADER LINE 的内表。</p>
<p>除非一些特殊情况，才会使用 HEADER LINE 内表。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><b>2.2.3 </b><b>内表数据处理</b></p>
<p><b>1. </b><b>遍历读取内表数据 (LOOP … ENDLOOP.)</b></p>
<pre class="brush: abap;">
LOOP AT emptab WHERE country BETWEEN ‘A’ AND ‘D’.

     WRITE:  / emptab-country, emptab-name1, emptab-sales.

ENDLOOP.

IF sy-subrc NE 0.   

     WRITE: / ‘NO ENTRIES’.   

ENDIF.

</pre>
<p>&nbsp;</p>
<p>解析：</p>
<p>a.LOOP 语句后，允许使用WHERE语句筛选数据。</p>
<p>b.程序中，出现 <b>sy-subrc</b> 变量，这是系统全局变量，用于检查是否符合条件,</p>
<p>  如若符合条件 sy-subrc 返回0 ，如果不符合，则返回4.</p>
<p>&nbsp;</p>
<p><b>2. </b><b>读取内表数据 (READ TABLE …)</b></p>
<p>在数据内表，可以通过READ TABLE关键字根据具体行数或主键字段读取内表中的某行记录：</p>
<pre class="brush: abap;">
TABLES: employee.

TYPES:  BEGIN OF emp,
         country     LIKE employee-country,
         name1       LIKE employee-name1,
        END OF emp.

DATA: emptab TYPE STANDARD TABLE OF emp INITIAL SIZE 10 WITH HEADER LINE.

SELECT * FROM EMPLOYEE.

    MOVE-CORRESPONDING employeeTO emptab.
    APPEND EMPTAB.

ENDSELECT.

READ TABLE ….

</pre>
<p>&nbsp;</p>
<p><b>READ TABLE </b><b>选项：</b></p>
<p><b style="color:red;">1) READ TABLE &lt;EMPTAB&gt;.</b></p>
<p><b style="color:red;">2) READ TABLE &lt;EMPTAB&gt;  WITH KEY &lt;k1&gt; = &lt;v1&gt;…  &lt;kn&gt; = &lt;vn&gt;.</b></p>
<p><b style="color:red;">3) READ TABLE &lt;EMPTAB&gt;  WITH TABLE KEY &lt;k1&gt; = &lt;v1&gt; &#8230;  &lt;kn&gt; = &lt;vn&gt;.</b></p>
<p><b style="color:red;">4) READ TABLE &lt;EMPTAB&gt;  WITH KEY  = &lt;value&gt;.</b></p>
<p><b style="color:red;">5) READ TABLE &lt;EMPTAB&gt;  WITH KEY . . .  BINARY SEARCH.</b></p>
<p><b style="color:red;">6) READ TABLE &lt;EMPTAB&gt;  INDEX &lt;i&gt;.</b></p>
<p><b style="color:red;">7) READ TABLE &lt;EMPTAB&gt; COMPARING &lt;f1&gt; &lt;f2&gt; . . . .</b></p>
<p><b style="color:red;">8) READ TABLE &lt;EMPTAB&gt; COMPARING ALL FIELDS.</b></p>
<p><b style="color:red;">9) READ TABLE &lt;EMPTAB&gt; TRANSPORTING &lt;f1&gt; &lt;f2&gt; . . . .</b></p>
<p><b style="color:red;">10) READ TABLE &lt;EMPTAB&gt; TRANSPORTING NO FIELDS.</b></p>
<p>&nbsp;</p>
<p>关键字说明：</p>
<p><b>[KEY|TABLE KEY]</b>: 通过内表的主键字段查找</p>
<p><b>[BINARY SEARCH]</b>: 二分法查找，使用该方法时，在READ TABLE之前，必须对内表排序</p>
<p><b>[INDEX]</b>: 根据内表索引查找</p>
<p><b>[COMPARING]</b>:只查找设置的字段</p>
<p><b>[COMPARING ALL FIELDS]</b>:查找内表所有的字段</p>
<p><b>[TRANSPORTING]</b>: 只输出设置的字段数据</p>
<p><b>[TRANSPORTING NO FIELDS]</b>: 不输出任何数据</p>
<p>&nbsp;</p>
<p><b>3. </b><b>内表排序</b></p>
<p>对内表进行排序，指定具体排序的排序字段、排序方式（升序/降序）</p>
<p>默认情况下，为升序。</p>
<p>语法：</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>SORT itab [BY &lt;f1&gt; &lt;f2&gt; …] [ASCENDING|DESCENDING]</strong></span></p>
<p>&nbsp;</p>
<p><b>4. </b><b>内表分类汇总（COLLECT TABLE …</b><b>）</b></p>
<p>通过COLLECT TABLE关键字，可以对内表中相同记录合并，若有数字类型(I、P、F)的字段，会将其合并汇总。</p>
<p>语法：</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>COLLECT [&lt;work area&gt; INTO] itab.</strong></span></p>
<p>&nbsp;</p>
<pre class="brush: abap;">

TABLES: EMPLOYEE.

TYPES:  BEGIN OF EMP,
	  COUNTRY    LIKE EMPLOYEE-COUNTRY,
	  SALES	     LIKE EMPLOYEE-SALES,
        END OF EMP.

DATA:  EMPTAB   TYPE STANDARD TABLE OF EMP INITIAL SIZE 10 WITH HEADER LINE,
       EMPTAB_C TYPE STANDARD TABLE OF EMP INITIAL SIZE 10 WITH HEADER LINE.

DATA:  EMPTAB_WA TYPE EMP.

* 赋值
EMPTAB-COUNTRY = 'D'.
EMPTAB-SALES         = 400.
APPEND EMPTAB.

EMPTAB-COUNTRY = 'USA'.
EMPTAB-SALES         = 1000.
APPEND EMPTAB.

EMPTAB-COUNTRY = 'GB'.
EMPTAB-SALES         = 500.
APPEND EMPTAB.

EMPTAB-COUNTRY = 'D'.
EMPTAB-SALES         = 7800.
APPEND EMPTAB.

SORT EMPTAB BY COUNTRY.

LOOP EMPTAB.
     
     MOVE-CORRESPONDING EMPTAB TO EMPTAB_WA.

     COLLECT EMPTAB INTO EMPTAB_C.

ENDLOOP.

</pre>
<p>输出结果：</p>
<p>D        8200</p>
<p>GB        500</p>
<p>USA      1000</p>
<p>&nbsp;</p>
<p>或者直接从数据表取数汇总：</p>
<pre class="brush: abap;">

SELECT * FROM EMPLOYEE.

   MOVE-CORRESPONDING EMPLOYEE TO EMPTAB.
   COLLECT EMPTAB.

ENDSELECT.

LOOP AT EMPTAB.

   WRITE:  / EMPTAB-COUNTRY, EMPTAB-SALES.

ENDLOOP.

</pre>
<p>&nbsp;</p>
<p><b>5.</b><b>系统字段 SY-TABIX </b></p>
<p>与前面提到的 <b style="color:red;">SY-SUBRC</b> 字段一样，<b style="color:red;">SY-TABIX</b> 也为系统的全局变量；</p>
<p>用于在循环遍历内表时，当前记录的索引值：</p>
<pre class="brush: abap;">

SELECT * FROM EMPLOYEE
   INTO CORRESPONDING FIELDS OF TABLE EMPTAB.

LOOP AT EMPTAB.

   WRITE:  / SY-TABIX, EMPTAB-COUNTRY, EMPTAB-NAME1.

ENDLOOP.

</pre>
<p>&nbsp;<br />
&nbsp;</p>
<p><b>2.2.4 </b><b>维护内表数据</b></p>
<p><b>1.</b><b>通过索引值维护内表</b></p>
<p>&nbsp;</p>
<p>语法:</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>INSERT   &lt;EMPTAB&gt; INDEX &lt;i&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>MODIFY &lt;EMPTAB&gt; INDEX &lt;i&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>DELETE   &lt;EMPTAB&gt; INDEX &lt;i&gt;.</strong></span></p>
<p>&nbsp;</p>
<p>说明：</p>
<p>INSERT： 向内表数据I处插入数据记录</p>
<p>MODIFY：修改内表数据I处记录</p>
<p>DELETE：删除内表I处数据记录</p>
<p>如：</p>
<pre class="brush: abap;">

SELECT * FROM EMPLOYEE.
   MOVE-CORRESPONDING EMPLOYEE TO EMPTAB.
   APPEND EMPTAB.
ENDSELECT.

READ TABLE EMPTAB INDEX 1.
MOVE 'ABC' TO EMPTAB-NAME1.
MODIFY EMPTAB INDEX SY-TABIX.

* 每次执行完之后，判断SY-SUBRC是否为0
IF SY-SUBRC NE 0.

   WRITE:  / ‘Attempt to modify failed.’.

ELSE.

  WRITE:  / EMPTAB-COUNTRY, EMPTAB-NAME1.

ENDIF.

INSERT EMPTAB INDEX 1.
DELETE EMPTAB INDEX SY-TABIX.

</pre>
<p>&nbsp;</p>
<p><b>2. </b><b>维护没有HEADER LINE</b><b>的内表</b></p>
<p>&nbsp;</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>APPEND &lt;work area&gt; TO &lt;internal table&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>COLLECT &lt;work area&gt; INTO &lt;internal table&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>INSERT &lt;work area&gt; INTO &lt;internal table&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>MODIFY &lt;internal table&gt; FROM &lt;work area&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>READ TABLE &lt;internal table&gt; INTO &lt;work area&gt;.</strong></span></p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>LOOP AT &lt;internal table&gt; INTO &lt;work area&gt;.</strong></span></p>
<p>&nbsp;</p>
<p>说明：</p>
<p>APPEND： 向内表追加数据</p>
<p>COLLECT：内表数据分类汇总</p>
<p>INSERT：向内表插入数据</p>
<p>MODIFY：修改内表数据</p>
<p>READ TABLE：读取内表数据</p>
<p>LOOP AT：遍历内表数据</p>
<p>&nbsp;</p>
<p><b>3. </b><b>清空内表</b></p>
<p>清空内表有4种方式：</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>CLEAR &lt;internal table&gt; </strong></span>：仅清空HEADER LINE，对内表数据存储空间不影响</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>REFRESH &lt;internal table&gt;</strong></span>：清空内表数据存储空间，对HEADER LINE不影响</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>FREE &lt;internal table&gt;</strong></span>：清空内表数据存储空间，对HEADER LINE不影响</p>
<p>&nbsp;</p>
<p><b>4.</b><b>获取内表信息</b></p>
<p>可以通过 <b style="color:red;">DESCRIBE</b> 关键字获取内表的相关信息。</p>
<p>语法：</p>
<p><span style="color: #ff0000; background-color: #fff000;"><strong>DESCRIBE TABLE &lt;internal table&gt; [LINES &lt;var1&gt;] [OCCURS &lt;var2&gt;].</strong></span></p>
<p>&nbsp;</p>
<p>说明：</p>
<p>LINES: 获取内表存储记录数</p>
<p>OCCURS：获取内表存储空间大小</p>
<p>&nbsp;<br />
&nbsp;<br />
&nbsp;</p>